#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>

int main(int argc, char const *argv[])
{
    /* code */
    int socket_ret = 0;
    fd_set readfds,tempfds; //定义select相关 描述符集合
    int value = 1;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t clientAddr_len = 0;

    /* 创建socket套接字 */
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 TCP 连接
    if (socket_fd == -1)
    {
        perror("socket\n");
        exit(-1);
    }
    socket_ret = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&value,sizeof(int));//配置端口重用
    if (socket_ret ==-1)
    {
        /* code */
        perror("setsocketopt\n");
    }
    
    /* bind绑定套接字 */
    memset(&server_addr, 0, sizeof(struct sockaddr)); //清空结构体
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(1235);              //设置本地端口，并转化为网络字节序 端口号用 htons 16位的来转换
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //默认获取本地网卡IP
    socket_ret = bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));
    if (socket_ret == -1)
    {
        perror("bind\n");
        close(socket_fd); //关闭socket 套接字 描述符
        exit(-1);
    }
    /* 建立linsten监听 */
    socket_ret = listen(socket_fd, 10);
    if (socket_ret == -1)
    {
        perror("listen\n");
        close(socket_fd); //关闭socket 套接字 描述符
        exit(-1);
    }
    FD_ZERO(&readfds);//初始化readfds
    FD_SET(socket_fd,&readfds);//把soket描述符添加到 描述符集合进行监控
    printf("FD_SETSIZE = %d\n",FD_SETSIZE);
    while (1)
    {
        /* code */
        tempfds = readfds;//select 会对readfds集合进行修改， 所以需要把集合中的 描述符保存下来
        /* 等待连接 */
        printf("wait connect .......\n");
        int client_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &clientAddr_len); //等待客户端连接
        if (client_fd == -1)
        {
            perror("accept\n");
            close(socket_fd); //关闭socket 套接字 描述符
            close(client_fd); //关闭socket 套接字 描述符
            exit(-1);
        }
        printf("client connect success\n");
        printf("有新的客户端接入，创建 新的线程来处理数据\n");
    }
    return 0;
}
